Skip to content

revert: listen v2 force-end-turn + diarize/word-confidence regen (#89) - #91

Merged
GregHolmes merged 2 commits into
mainfrom
revert/listen-v2-regen-89
Aug 11, 2026
Merged

revert: listen v2 force-end-turn + diarize/word-confidence regen (#89)#91
GregHolmes merged 2 commits into
mainfrom
revert/listen-v2-regen-89

Conversation

@GregHolmes

@GregHolmes GregHolmes commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Reverts the listen v2 regen (5b6323a, originally #89: Flux force-end-turn, listen v1 diarize metadata + arch, word speaker confidence, AgentV1UpdateListen provider retype, ListenV2Redact) off main.

Mirrors the equivalent revert on deepgram-python-sdk: deepgram/deepgram-python-sdk#757

Why

This work isn't ready to ship yet, and other priorities need to release from main without it. Since the regen is already on main, any release cut from main (including the pending release-please 0.7.2, #90) would publish it. Reverting removes it from the release line cleanly, without rewriting history.

Redoing the regen

The regen commit 5b6323a stays reachable in history (and on the #89 branch), and the next regen branch gh/sdk-gen-2026-08-11 (#92) is stacked on this revert. Caveat: re-landing is a fresh 4.16.0 regen, not a replay of #89's hand-patches — see "Forfeited by this revert" below.

Also reverted (not spec features)

Beyond the five spec features, this 184-file revert also rolls back:

  • Fern toolchain downgrade (.fern/metadata.json): cliVersion 5.89.0 → 5.44.6, generatorVersion 4.16.0 → 4.10.1, runtime-version dropped. This is what makes most of the rest follow.
  • Restores the ClientOptions.java .fernignore freeze block + its release-please generic extra-file entry (both dropped by feat(regen): add diarize_info, Flux force-end-turn, update-listen, word speaker confidence #89) — this is what keeps X-Fern-SDK-Version release-please-bumpable (no wire-version drift).
  • Removes the three 4.16.0-era stopgap freeze blocks (type-rename, return-type shim, union default-variant) and the ListenV2ForceEndTurn hashCode() entry from .fernignore and AGENTS.md.
  • README.md: removes the 4.16.0 retry-knob docs (retry-behavior prose that remains accurate has been restored — see the diff).

Forfeited by this revert (tracked in #93)

The revert also drops patches #89 carried that are not preserved on gh/sdk-gen-2026-08-11 and not among #92's 17 reconciled patches (verified: all three unions read defaultImpl = _UnknownValue.class on #92, both tests absent):

  • Union default-variant fix (defaultImpl = V2Value) on AgentV1UpdateListenListenProvider, AgentV1SettingsAgentListenProvider, AgentV1SettingsAgentContextListenProvider. The two Settings unions carry this bug in released 0.7.1 (pre-existing, not a regression), so the revert restores released behavior — it forfeits an unreleased fix.
  • AgentV1UpdateListenListen.getProvider() additive return-type shim.
  • Regression guards AgentV1UpdateListenShimTest.java, AgentSettingsProviderDefaultTest.java.

Whether to re-apply the defaultImpl fix on #92 is a deliberate decision tracked in #93.

Verification

  • ./gradlew compileJava compileExamples unitTest — build successful, all unit tests pass.
  • The revert is a clean inverse of the single regen commit (184 files): git diff 5b6323a^ HEAD over the pre-README-fix tree is empty (byte-identical to the 0.7.1 release commit 8b3c605). Restores pre-regen .fern/metadata.json (sdkVersion 0.7.1, generator 4.10.1), the .fernignore freeze blocks, and the release-please-config.json ClientOptions.java generic entry.
  • Escape-hatch (additionalProperties), forward-compat no-op, and fields-less hashCode() patches from 0.7.1 all survive.

…sten, word speaker confidence (#89)"

This reverts commit 5b6323a.

@dg-coreylweathers dg-coreylweathers left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving.

Verified the revert is a clean inverse of 5b6323a — the pre-README-fix tree is byte-identical to the 0.7.1 release commit 8b3c605 — and that 0.7.1's hand patches all survive: the additionalProperties streaming escape hatch, the forward-compat unknown-frame no-op, the fields-less hashCode() set, the ReconnectingWebSocketListener fixes, and the ClientOptions version-marker freeze (plus its release-please generic entry, which is what keeps X-Fern-SDK-Version bumpable with no wire-version drift).

All four review findings actioned:

  • B1#90 closed, and the body no longer claims release-please will regenerate its own release notes.
  • B2#93 filed and closed; the body now has a "Forfeited by this revert" section naming all three items and stating plainly that an unreleased fix is forfeited while released behaviour is restored. The defaultImpl = V2Value fix is re-applied on all three provider unions in #92, with AgentSettingsProviderDefaultTest restored. AgentV1UpdateListenShimTest is correctly not restored — it guarded the shim #92 deliberately drops.
  • S178c4601 restores the accurate retry-behavior prose, keeping only the genuinely-removed tuning knobs out.
  • S2 — the body now discloses the non-spec scope (Fern toolchain downgrade, freeze-block bookkeeping, README change).

Merge this before #92 — verified git merge-tree is clean in both directions and that the merged tree retains 78c4601's prose.

One heads-up: release-please.yml triggers on push to main, so merging this will open a fresh 0.7.2 release PR whose changelog still advertises the reverted #89 features — 5b6323a remains in range since the v0.7.1 tag and release-please cannot cancel a feat with a revert. Don't merge that release PR; close it as with #90, or park it until #92 lands and hand-delete the 5b6323a Features line before cutting 0.8.0.

@GregHolmes
GregHolmes merged commit 19e02f5 into main Aug 11, 2026
11 checks passed
GregHolmes added a commit that referenced this pull request Aug 12, 2026
…provider + google version (#92)

Regenerates the SDK against the latest Fern generator (`4.10.1` →
`4.16.0`) and API spec (`ff8fd2b` → `03f0677`), reconciles the
hand-maintained patches, and documents the resulting breaking changes
with a migration guide. Supersedes the reverted #89.

## Base
Stacked on the revert branch (#91). Until that merges, this PR's diff
includes the revert commit; merge #91 first (or it rides along).

## ⛔ Blocked / do not merge yet
Regenerated from an **unmerged spec branch**: `.fern/metadata.json`
`originGitCommit` `03f0677` lives only on `origin/jherlihy/flux-tts-ga`,
not on `deepgram-docs` `main`. The launch surface here
(`breaks_applied`, `ConfigureFailure`, `expressivity`, `speed`,
`redact`) exists only on that branch. Kept as a **draft** until it
lands.
- **Blocked-on:** `deepgram-docs#1094` (Flux TTS copy) + the
`jherlihy/flux-tts-ga` spec branch merging to `deepgram-docs` `main`.

## Breaking changes (pre-1.0, source/compile-time only)
All three follow the API definition; on-the-wire payloads for existing
requests are unchanged. Full before/after in
[`docs/Migrating-v0.7-to-v0.8.md`](./docs/Migrating-v0.7-to-v0.8.md).

1. **`AgentV1UpdateListenListen.provider`** retyped
`DeepgramListenProviderV2` → `AgentV1UpdateListenListenProvider` (V1/V2
union). Wrap with `AgentV1UpdateListenListenProvider.v2(...)`; read via
`getV2()`.
2. **`Google.version`** retyped `Optional<String>` →
`Optional<GoogleThinkProviderVersion>`. Use the enum constants
(`V1BETA`, `AI_STUDIO_V1BETA`, `GEMINI_ENTERPRISE_AGENT_V1`).
3. **`SpeakV2SpeechMetadataControlsApplied`** gains a required
`breaksApplied` field (new builder step; new `getBreaksApplied()`). Read
paths unaffected.

Origin verified: #2 and #3 are new in the latest spec; #1's union shape
existed in #89 but was previously hidden behind an in-SDK shim we
intentionally did not carry forward.

## Reconciliation (post-regen review)
Diffed each of the 17 `.bak` patches against the freshly generated
originals — **all 17 still needed**, none dropped. `.fernignore`
restored to its pre-prep state; all `.bak` files deleted.
- **13 restored verbatim** (generator produced no other changes): the 11
fields-less `hashCode()` types, `ReconnectingWebSocketListener`
(override hook / `connectionTimeoutMs` / `maxRetries(0)` semantics), and
the `listen/v1` + `speak/v1` websocket clients (query-param repeats +
`additionalProperties`).
- **2 surgically merged** (`listen/v2` + `speak/v2` websocket clients):
re-applied `QueryStringMapper` array-param serialization, the
`additionalProperties` escape hatch, and the forward-compat
unknown-message no-op, **while keeping the generator's new features**
(speak/v2 `sendInterrupt`/`sendConfigure` +
`onSpeechInterrupted`/`onConfigureSuccess`/`onConfigureFailure`;
listen/v2 `redact`).
- **`ClientOptions`**: kept the new retry-tuning options +
`ResponseDecompressionInterceptor`; re-applied only the two `//
x-release-please-version` header lines (colon SDK-name form), removed
the generator's `getSdkVersion()` helper (build does not stamp the JAR
manifest, so it would drift).

## Additive highlights
Speak V2 interrupt/configure, Listen V2 `redact`, Speak V2
`speed`/`expressivity`, new Deepgram Flux TTS voices, client retry
tuning, automatic response decompression.

## Tests added
- `ListenV2ConnectWireTest`: new `redact` connect param (present as wire
`numbers`, omitted when absent).
- `RegenTypesTest` → "2026-08-11 regen type shapes": the three breaking
shapes (provider union v2 factory/`getV2`/serialization,
`Google.version` enum wire value, `ListenV2Redact` wire values).

## Verification
- `./gradlew unitTest` ✅ · `spotlessCheck` ✅ · `compileExamples` ✅
- `./gradlew integrationTest` ✅ (Tier 1 + Tier 2 against a live key);
opt-in Speak V2 WS integration ✅ (returned audio over the new v2 WS
path)
- Ran all non-`manage` examples: 19 pass, 7 long-running streaming/agent
examples connected and worked, 4 environmental (proxy / file-arg /
callback URL / SageMaker) — no SDK regressions.

## Post-review additions (from #91 review)
- **Re-applied the union default-variant fix** the #89 revert forfeited
(issue #93): `defaultImpl = V2Value` on
`AgentV1UpdateListenListenProvider`,
`AgentV1SettingsAgentListenProvider`,
`AgentV1SettingsAgentContextListenProvider`, so a provider payload
omitting the optional `version` discriminator (what 0.7.x emits)
deserializes as V2 instead of dropping to `{"provider":null}`. Frozen in
`.fernignore` + `AGENTS.md`, guarded by the re-added
`AgentSettingsProviderDefaultTest`. The `getProvider()` return-type shim
is intentionally **not** re-applied — that retype is a deliberate
breaking change (see the migration guide).

## Core behavior changes (generator 4.10.1 → 4.16.0)
Beyond the spec features, the generator upgrade changes core HTTP-client
behavior worth calling out in the release notes:
- **Automatic response decompression** is now installed by default
(`ResponseDecompressionInterceptor`): gzip/deflate-encoded HTTP
responses are transparently decoded. No API change; transparent to
callers.
- **New optional retry tuning** on `ClientOptions.Builder`:
`initialRetryDelayMillis`, `maxRetryDelayMillis`, `retryJitterFactor`.
All defaulted — existing behavior is unchanged unless set.

## Follow-ups
- Once this lands, release-please cuts a fresh release at **0.8.0**
(breaking `feat!`).
- **Changelog needs a manual edit before releasing.** `5b6323a` (#89
`feat(regen)`) is still in release-please's range since `v0.7.1`, and
release-please can't pair a revert with the commit it reverts — so the
generated 0.8.0 notes will re-list the reverted #89 features
(`diarize_info`, force-end-turn) under Features. Hand-edit the release
PR's `CHANGELOG.md` to drop them before merging it.

BREAKING CHANGE: `AgentV1UpdateListenListen.provider` is now
`AgentV1UpdateListenListenProvider` (V1/V2 union); `Google.version` is
now `Optional<GoogleThinkProviderVersion>`;
`SpeakV2SpeechMetadataControlsApplied` has a new required
`breaksApplied` field. See docs/Migrating-v0.7-to-v0.8.md.

---------

Co-authored-by: fern-api[bot] <115122769+fern-api[bot]@users.noreply.github.com>
GregHolmes added a commit that referenced this pull request Aug 19, 2026
…nale

Two gaps in the preceding regen-reconciliation commit.

1. ListenV2ForceEndTurn was generated unpatched.

   It is a 12th fields-less message type with equals() and no hashCode(), so it
   violated the Object contract like the other 11. Diffing .bak files could not
   catch it: the type is newly generated (reverted out in #91, reintroduced by
   4.18.0), so it had no .bak to compare against.

   Added the hashCode() patch, froze it in .fernignore, listed it in AGENTS.md,
   and extended RegenTypesTest.FieldsLessMessageContract to assert it. Added a
   post-regen sweep step to AGENTS.md so a newly generated fields-less type
   cannot slip through this way again.

2. The ClientOptions rationale in the previous commit message and the PR body
   was wrong on a point of fact.

   It claimed 4.18.0's getSdkVersion() helper "always resolves null" because
   build.gradle sets no jar manifest attributes. That is only true for Gradle
   builds and tests. The published artifact is built by Maven (release-please.yml
   runs `mvn deploy -P release`) and pom.xml's maven-jar-plugin sets
   addDefaultImplementationEntries=true, so the published JAR manifest does carry
   Implementation-Version and the generator's helper would resolve correctly
   there.

   The decision to keep the explicit literals still stands, on the accurate
   rationale: they are correct under Gradle, Maven, and tests alike, whereas
   getSdkVersion() is correct only via Maven and silently reports a stale
   generator-authored fallback everywhere else. release-please already lists this
   file in extra-files, so the markers are actively wired. Recorded in AGENTS.md.

Verified: ./gradlew test compileExamples -> 112 tests, 0 failures, 1 skipped.
dg-coreylweathers pushed a commit that referenced this pull request Aug 25, 2026
…vider/agent-history types (#96)

Fern SDK regeneration for 2026-08-19 (`fern-java-sdk` **4.16.0 →
4.18.0**, CLI 5.44.6 → 5.95.1, spec `03f0677` → `068de88`).

**Status:** reconciled & verified. All 8 CI checks green — Spotless,
Compile (Java 11/17/21), Unit Tests (Java 11/17/21), Title Check.
Locally `./gradlew spotlessCheck test compileExamples` → **123 passed /
1 skipped** (the skip is the opt-in `SpeakV2WebSocket` test; with
`DEEPGRAM_SPEAK_V2_WS=1` it passes, making `integrationTest` 7/7).

Ships **2 breaking source changes**, both documented in
[`docs/Migrating-v0.8-to-v0.9.md`](./docs/Migrating-v0.8-to-v0.9.md).
Both are source-level renames with identical wire values, so no request
payload changes and a clean recompile is the whole migration.

## New in this regen

- **Listen V2 force-end-turn** — `sendForceEndTurn()` +
`ListenV2ForceEndTurn`, plus `ListenV2TurnInfo.getTrigger()`
(`Optional<String>`, open-typed) identifying what ended a turn. **Now
enabled on staging and verified end-to-end; still gated on production —
see [Force-end-turn: verified on staging, gated on
production](#force-end-turn-verified-on-staging-gated-on-production).**
- **Listen V1 diarization detail** — `getDiarizeInfo()` on the
response/results metadata (`getModelUuid()`, `getArch()`) identifying
which diarizer ran, plus per-word `getSpeakerConfidence()`
(`Optional<Float>`) on pre-recorded words items. `speaker_confidence` is
pre-recorded only, not streaming.
- **25 new `DeepgramModel` constants**, including the Flux TTS voices.
- **Provider/agent-history type renames** — the generator dropped the
`*ThinkProvider*` / `*SpeakProvider*` prefixes and consolidated the
agent conversation-history leaf types.

## Force-end-turn: verified on staging, gated on production

**Updated 2026-08-20 — this supersedes the earlier "cannot be tested
end-to-end" finding.** The gate has since opened on staging, so the
feature is now verified against a live server through the SDK's own
`V2WebSocketClient` (not a raw socket): stream real audio, force the
turn to end mid-sentence, read back `trigger`.

| Probe | `api.staging.deepgram.com` | `api.deepgram.com` |
|---|---|---|
| Baseline connect + stream audio | Connected, `TurnInfo` flowing |
Connected, `TurnInfo` flowing |
| `{"type":"ForceEndTurn"}` | **Accepted** — no error, socket stays open
| `UNPARSABLE_CLIENT_MESSAGE` — *"The ForceEndTurn message is not
enabled on this deployment."*, socket closed |
| `EndOfTurn` after the force | `trigger=manual`,
`end_of_turn_confidence=0.0081` | never reached — socket closed first |
| Natural `EndOfTurn` (no force) | `trigger=model`,
`end_of_turn_confidence=0.773` | `trigger` absent |

Two details confirm the feature genuinely works rather than the turn
coincidentally ending:

- **`end_of_turn_confidence=0.0081` on the forced turn.** The model was
nowhere near ending it — compare `0.773` at a natural end. The turn
ended because we asked.
- **The stream survives and advances.** After the forced end the turn
index incremented, `StartOfTurn` fired again, and transcription
continued. That is the intended semantic, not a disconnect.

**No SDK change was needed.** `sendForceEndTurn()` serialized correctly
and `getTrigger()` deserialized both `manual` and `model` unmodified.
Typing `trigger` as an open `Optional<String>` rather than a closed enum
is what made that hold.

### Correcting the earlier evidence

The previous revision argued the gate was closed everywhere partly
because *"`trigger` came back absent on every `TurnInfo`."* That was
weaker than it read: `trigger` is documented as present on `EndOfTurn`
**and only there**, and any probe that sends `ForceEndTurn` to a gated
deployment gets its socket closed before reaching an `EndOfTurn` — so
the observation was equally consistent with `trigger` working fine. The
bottom row above closes that hole by streaming through to a *natural*
`EndOfTurn`: on production `trigger` is still absent there, which is the
claim that actually needed support.

**Caveat, unchanged:** one API key per environment, so this shows the
gate is open *for that staging project*. Whether enablement is
per-project, per-deployment, or global still needs someone with the
feature-flag config.

This is also why #91 reverted force-end-turn previously. The difference
now is that the typed surface ships with an accurate enablement warning
— and, on a deployment that has it, live coverage.

## Breaking changes (documented, not shimmed)

Java has no type aliases, so there is no way to keep the old names as
exact aliases of the new ones. A deprecated constants-only shim class
would fix inline call sites like
`.model(DeepgramSpeakProviderModel.AURA2ASTERIA_EN)`, but it cannot
preserve a **return type** — and `Optional<GoogleThinkProviderVersion> v
= google.getVersion()` is the exact line 0.8.0's own migration guide
told users to write. Binary compatibility is broken regardless, so every
consumer recompiles. This repo has no `@Deprecated` anywhere and shipped
0.8.0 as `feat(regen)!` with a migration guide; this cycle follows that
convention.

**9 renames** (constant names and wire values unchanged):

| v0.8.x | v0.9.0 |
| --- | --- |
| `AnthropicThinkProviderModel` | `AnthropicModel` |
| `CartesiaSpeakProviderModelId` | `CartesiaModelId` |
| `CartesiaSpeakProviderVoice` | `CartesiaVoice` |
| `DeepgramSpeakProviderModel` | `DeepgramModel` |
| `GoogleThinkProviderModel` | `GoogleModel` |
| `GoogleThinkProviderVersion` | `GoogleVersion` |
| `GroqThinkProviderReasoningMode` | `GroqReasoningMode` |
| `AgentV1HistoryContentRole` | `ConversationHistoryMessageRole` |
| `AgentV1HistoryFunctionCallsFunctionCallsItem` |
`FunctionCallHistoryMessageFunctionCallsItem` |

`OpenAiThinkProvider*` is not renamed (it collides, so the generator
keeps the long form).

**2 duplicate types removed** —
`AgentV1SettingsAgentContextContextMessagesItemContentRole` and
`...FunctionCallsFunctionCallsItem` are replaced by the canonical
`ConversationHistoryMessageRole` /
`FunctionCallHistoryMessageFunctionCallsItem`. Verified structurally
identical: same constants, same `"user"`/`"assistant"` wire values.

**The ripple is wider than the type list implies.** A `javap` surface
diff over all 1688 public types at 0.8.0 vs HEAD found **53 removed
public types** and **30 removed public members across 21 surviving
types** — because seven carrier types changed both getter return types
and builder parameter types: `Anthropic`, `Cartesia`, `Deepgram`,
`Google`, `Groq`, `ConversationHistoryMessage`,
`FunctionCallHistoryMessage`. The migration guide lists each with its
affected members.

**Every removal traces to those 11 renamed/deleted types — zero
unexplained removals, and no new required builder stages**, so there is
no 0.8.0-style "gained a required field" break hiding in here.

## Two generator regressions patched, not shipped

### `speak.v2` connect `speed`

The generator retyped `V2ConnectOptions.speed` from `Optional<Double>`
to a closed 7-value string-literal enum. **Not shipped** — restored to
`Double` and frozen, so existing `.speed(1.05)` callers are unaffected.

The generated type contradicts the API contract two ways: the mid-stream
`SpeakV2Configure.speed` on the same connection is still
`Optional<Double>`, and the server parses the numeric form and
range-checks it (`SPEED_OUT_OF_RANGE` outside `0.85`–`1.15`,
`SPEED_INCREMENT_INVALID` off the `0.05` increment) — so a closed enum
cannot express a valid in-range value it omits. Guarded by
`SpeakV2ConnectWireTest`; the generated `SpeakV2Speed` type is left in
place, unused, as documentation of the accepted values, and it appears
in no public signature. Unfreeze when the spec types the connect `speed`
as a number.

### `DeepgramModel.FLUX_RENEE_EN`

The generator removed this constant. **Not shipped** — restored and
frozen. Verified against the live API rather than assumed:

- `POST /v2/speak?model=flux-renee-en` → **200** with a valid 3.1s MP3
(MPEG layer III, 48 kbps, 24 kHz mono — Flux TTS's output format).
- The name resolves in the server's model **registry, not by prefix**:
an invented `flux-bogus-nonexistent-en` is rejected with
`INVALID_QUERY_PARAMETER`, while `flux-renee-en` is accepted.
- It also appears in a July 2026 internal regression sweep across all
speakers and in current voice rosters, with no deprecation or sunset
language.

So the removal is a spec regression, not a retirement. All five
touchpoints restored (constant, `Value` enum, `visit()` case,
`valueOf()` case, `Visitor` method); guarded by a `RegenTypesTest` case
asserting the wire value, `valueOf()` resolution, and JSON round-trip.
**The 25 additions are all retained — the enum now has 100 constants,
with nothing removed relative to 0.8.0.**

⚠️ Freezing `DeepgramModel` carries a risk the other frozen files don't:
it receives frequent additive spec changes, so restoring its `.bak`
wholesale on a future regen would silently drop new voices.
`.fernignore` and `AGENTS.md` both carry an explicit warning to diff and
carry additions forward instead.

## Patch reconciliation

**4.18.0 fixed none of the five existing defect groups.** All 20 frozen
files re-patched, all 20 `.fernignore` paths restored; 3 files newly
frozen (`V2ConnectOptions`, `ListenV2ForceEndTurn`, `DeepgramModel`).
Every `.bak` deleted.

| Patch group | Files | Evidence in 4.18.0 output |
|---|---|---|
| Fields-less `hashCode()` | 11 → **12** | Still emits `equals()` with
no `hashCode()` |
| Union `defaultImpl` | 3 | Still `defaultImpl = _UnknownValue.class` |
| WS array query-params | 3 | Still `addQueryParameter("keyterm",
String.valueOf(...))` |
| WS `additionalProperties` | 4 | `connect()` still never emits them |
| Forward-compat no-op | 2 | Unknown frames still routed to `onError` |
| `ReconnectingWebSocketListener` | 1 | `retryCount >= maxRetries`,
hardcoded `4000`, no `applyOptionsOverride` |

**`ListenV2ForceEndTurn` reached the branch unpatched.** It is a 12th
fields-less type with `equals()` and no `hashCode()`. Diffing `.bak`
files structurally cannot catch this — the type was reverted out in #91
and reintroduced by 4.18.0, so it was newly generated with no `.bak` to
compare against. Now patched, frozen, and asserted by `RegenTypesTest`.
A post-regen sweep step was added to `AGENTS.md` so this class of miss
cannot recur.

**`applyOptionsOverride` is load-bearing.**
`core/transport/TransportWebSocketFactory.java:39` calls it and is
permanently frozen, so main source does not compile without the patch.

**`ClientOptions` stays frozen.** 4.18.0 replaced the version literals
with `getSdkVersion()` reading `Package.getImplementationVersion()`.
That *does* resolve in the published artifact (CI runs `mvn deploy -P
release`; `pom.xml`'s maven-jar-plugin sets
`addDefaultImplementationEntries=true`), but resolves to `null` under
Gradle and in tests, falling back to a generator-authored literal
nothing keeps current. `.github/release-please-config.json` already
lists this file in `extra-files`, so the `// x-release-please-version`
markers are actively wired. Also keeps `User-Agent` on the
`com.deepgram:` coordinate form to match `X-Fern-SDK-Name`.

**`AGENTS.md` validation command corrected** to `./gradlew spotlessCheck
test compileExamples`. CI runs Spotless as its own job, so the
previously documented `test compileExamples` passed locally while CI
failed — which happened on this branch. Hand-re-applying patches trips
the formatter routinely, since inserted comments and renamed types
change how chained calls wrap.

## Verification

- **CI:** all 8 checks green.
- **Unit:** `unitTest` → 106 passed, 0 skipped. Every patch group's
regression guard passes: `applyOptionsOverride` (2), `maxRetries(0)`
(1), `ReconnectOptions builder` (4), fields-less `hashCode()` (1),
`FLUX_RENEE_EN` (1), `AgentSettingsProviderDefaultTest` (3), both
forward-compat tests, and the wire tests (`ListenV1` 7, `ListenV2` 9,
`SpeakV2` 7, `StreamingAdditionalProperties` 4, `QueryStringMapper` 12).
- **Integration (live API):** `integrationTest` → **8/8** with
`DEEPGRAM_SPEAK_V2_WS=1` and `DEEPGRAM_LISTEN_V2_FORCE_END_TURN=1`
against staging; 6/8 with 2 skips against production, where both gated
features are unavailable. There is no separate e2e suite — the live-API
integration tests plus the examples are that layer.
- **Examples:** all 32 non-`manage` examples run (31 previously, plus
the new `listen/ForceEndTurn`). 20 exit clean; 7 time out and 4 fail,
and **every one of those 11 reproduces identically on a 0.8.0
worktree**, so there are no example regressions. The failures are
environmental (no local proxy, a missing CLI argument, a missing audio
file, a placeholder callback URL) and the timeouts are streaming
examples that finish their work but leave a non-daemon executor holding
the JVM open, plus three agent examples hitting server-side
`CLIENT_MESSAGE_TIMEOUT` / `INVALID_SETTINGS`. All pre-existing.
- **Rename safety:** across all six renamed enums, **0 wire values
changed and 0 constants lost** — the renames are purely nominal.
- **API surface:** `javap` diff vs 0.8.0 confirms the breaking scope is
bounded to the renames.
- **Live API:** `flux-renee-en` confirmed serving; force-end-turn
confirmed working on staging (`trigger=manual`) and still gated on
production.

### Version bump

Title is `feat(regen)!` so release-please computes a minor bump to
`0.9.0` from the squash-merge message. The `!` matters — the migration
guide is written for `0.8` → `0.9`.

## Test coverage added

The new surface from this regen arrived untested; that is now closed.

- **`ListenV2ControlFrameWireTest`** (new) — `sendForceEndTurn` had no
test at all. Asserts the frame arrives, that it carries nothing but the
discriminator (exact match, since the server rejects unknown fields on
control messages), and `sendCloseStream` as a control so a future
failure separates "send path broke" from "ForceEndTurn broke". This runs
on every build regardless of deployment gating, so it stays the baseline
guard wherever the live test skips.
- **`RegenTypesTest.Regen20260819`** (new) — 7 cases over
`ListenV2TurnInfo.trigger`, both `DiarizeInfo` variants, and words-item
`speaker_confidence`, parsed from realistic server payloads rather than
builder round-trips. Each is also asserted **absent**, since absence is
normal: `trigger` appears only on `EndOfTurn`, `diarize_info` only with
diarization on, and `speaker_confidence` is pre-recorded only. The
`trigger=manual` fixture matches what the live server returns verbatim.
- **`IntegrationTest.testIntegration_ListenV2ForceEndTurn`** (new) — the
first live-API coverage of the listen v2 WebSocket in this repo, which
previously had none at all. Streams real audio, waits for `StartOfTurn`
so there is a turn to end, forces it, and asserts `trigger=manual` with
no server error. Opt-in via `DEEPGRAM_LISTEN_V2_FORCE_END_TURN=1`, so it
skips cleanly where the feature is gated rather than failing the build —
same pattern as the existing `DEEPGRAM_SPEAK_V2_WS` test. Verified
passing against staging and skipping against production.
- **`examples/listen/ForceEndTurn.java`** (new) — no example used
`sendForceEndTurn`, and `LiveStreamingV2` never actually streams audio,
so no example reached a `TurnInfo` at all. This one streams real audio,
forces a turn end, and prints the `trigger`. On a gated deployment it
reports that and exits cleanly rather than crashing. Verified against
both.
- **`IntegrationTest`** — the `SpeakV2WebSocket` test now sets
`speed(1.05)`, so the `speed` patch is exercised against a real server
rather than only a mock. Verified passing live.

## ⚠ Merging: the squash message needs a `BREAKING CHANGE:` footer

**This is required, not optional.** release-please builds the `### ⚠
BREAKING CHANGES` section of `CHANGELOG.md` from a literal `BREAKING
CHANGE:` footer in the squash-merge commit body — that is how 0.8.0's
entry got its text. **No commit on this branch has one**, and the `!` in
the title alone only triggers the version bump; it does not produce the
explanatory text or the migration-guide link. Merging with GitHub's
default (this whole review document as the commit body) would ship 0.9.0
with an unexplained breaking-changes section.

Use this as the squash-merge message instead:

```
feat(regen)!: listen v2 force-end-turn + diarize metadata; rename provider/agent-history types

Regenerates against Fern generator 4.16.0 -> 4.18.0 (CLI 5.44.6 -> 5.95.1,
spec 03f0677 -> 068de88), re-applies the hand-maintained patches, and
documents the resulting breaking changes with a migration guide.

Features:
- Listen v2 force-end-turn: sendForceEndTurn() + ListenV2ForceEndTurn, plus
  ListenV2TurnInfo.getTrigger() identifying what ended a turn. Requires
  server-side enablement and is rejected on staging and production today, so
  the typed surface ships but must not be depended on yet.
- Listen v1 diarization detail: getDiarizeInfo() (model_uuid, arch) on the
  response and results metadata, plus per-word getSpeakerConfidence() on
  pre-recorded words items.
- 25 new DeepgramModel voice constants, including the Flux TTS voices.

Two generator regressions are patched rather than shipped: the speak v2
connect `speed` param stays Optional<Double> (the generator retyped it to a
closed string enum, contradicting the numeric API contract), and
DeepgramModel.FLUX_RENEE_EN is restored (the voice is live and serving; the
removal was a spec regression).

BREAKING CHANGE: the provider and agent-history types lost their role prefixes — `AnthropicThinkProviderModel` → `AnthropicModel`, `CartesiaSpeakProviderModelId` → `CartesiaModelId`, `CartesiaSpeakProviderVoice` → `CartesiaVoice`, `DeepgramSpeakProviderModel` → `DeepgramModel`, `GoogleThinkProviderModel` → `GoogleModel`, `GoogleThinkProviderVersion` → `GoogleVersion`, `GroqThinkProviderReasoningMode` → `GroqReasoningMode`, `AgentV1HistoryContentRole` → `ConversationHistoryMessageRole`, `AgentV1HistoryFunctionCallsFunctionCallsItem` → `FunctionCallHistoryMessageFunctionCallsItem`. The duplicate `AgentV1SettingsAgentContextContextMessagesItemContentRole` and `...FunctionCallsFunctionCallsItem` are removed in favour of the canonical types. Getter return types and builder parameters on `Anthropic`, `Cartesia`, `Deepgram`, `Google`, `Groq`, `ConversationHistoryMessage` and `FunctionCallHistoryMessage` change accordingly. All wire values are unchanged, so no request payloads change. See docs/Migrating-v0.8-to-v0.9.md.
```

Unlike 0.8.0, the release-please range is clean — `v0.8.0..main` is
empty, so this squash commit will be its only input and there is no
reverted-commit pairing to hand-edit out of the release PR this time.

## Follow-ups

- Two spec-side regressions are patched but not yet filed upstream: the
`speed` retype and the dropped `FLUX_RENEE_EN` constant. That is two
items on top of the six existing open Fern requests, none of which
4.18.0 addressed.
- Force-end-turn is verified on staging but still gated on production.
Re-run `integrationTest` with `DEEPGRAM_LISTEN_V2_FORCE_END_TURN=1`
against production once the gate lifts there; the test is written to
need no changes when it does, and the `trigger` wording in the migration
guide can drop its enablement caveat at that point.

---------

Co-authored-by: fern-api[bot] <115122769+fern-api[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants